package com.carleasoft.mps.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.carleasoft.mps.core.perm.DataPermCache;
import com.carleasoft.mps.core.perm.ThreadPermDataContext;
import com.carleasoft.mps.core.result.R;
import com.carleasoft.mps.core.user.ThreadUserContext;
import com.carleasoft.mps.core.user.UserCacheData;
import com.carleasoft.mps.core.utils.JwtTokenUtil;
import com.carleasoft.mps.core.utils.SecurityConsts;
import com.carleasoft.mps.data.redis.JedisService;
import com.carleasoft.mps.data.redis.base.CacheKeyEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Set;

/**
 *Description: 网关请求全局过滤器 做全局日志处理
 */
public class RequestPermissionFilter implements GlobalFilter, Ordered {

    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Autowired
    JedisService jedisService;
    /**
     * 全局过滤
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Mono<Void> result = null;
        //获取对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String requestUrl = request.getPath().pathWithinApplication().value();
        String[] split = requestUrl.split("/");
        String prefix = split[1];
        // 用户模块不走此处校验
        if(prefix.equals("adu")) {
            result = chain.filter(exchange);
        } else {
            Set<String> ignoreUrls = (Set<String>)jedisService.getObject(CacheKeyEnum.PREFIX_WITHE_API,prefix + "_WITHE_API");
            /*校验 白名单token*/
            if(ignoreUrls.contains(requestUrl)){
                result = chain.filter(exchange);
            }
            else {
                // 判断 token 是否正确
                String token = request.getHeaders().getFirst("Authorization-Token");
                if(StringUtils.isEmpty(token)){
                    //token为空
                    result = this.getVoidMono(response,"没有token！！！","000001");
                } else {
                    String account = JwtTokenUtil.getClaim(token, SecurityConsts.ACCOUNT);
                    // 校验 token 是否正确
                    Boolean aBoolean = this.bindCheck(account);
                    if(aBoolean){
                        System.out.println(ThreadUserContext.getCurrentCacheUser());
                        result = chain.filter(exchange);
                    } else {
                        result = this.getVoidMono(response,"token失效！！！","000001");
                    }
                }
            }
        }
        return result;
    }
    /**syst
     * 默认排序
     */
    @Override
    public int getOrder() {
        return 1;
    }
    /**
     * 异常返回
     */
    private Mono<Void> getVoidMono(ServerHttpResponse response, String msg ,String code){
        R resultBody = new R();
        resultBody.message(msg);
        resultBody.code(code);
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        response.getHeaders().add("Cache-Control", "no-cache");

        DataBuffer dataBuffer = response.bufferFactory().wrap(JSON.toJSONString(resultBody).getBytes());
        return response.writeWith(Mono.just(dataBuffer));
    }


    /**
     * 根据登录账号获取用户缓存数据，获取不到则重新走登录
     * 因为移动端缓存登录token时间比较长
     * @param account
     * @return
     */
    private Boolean bindCheck(String account) {
        //对权限要求需要实时响应的，且权限容易经常调整的，需要实时调用权限接口，否则采用缓存存储，避免每次接口访问都需要从数据库查询计算
        if(StringUtils.isEmpty(account)) {
            return false;
        }
        DataPermCache dataPermCache =(DataPermCache)jedisService.getObject(CacheKeyEnum.PREFIX_PERMS_CACHE_DATA,account);
        UserCacheData userCacheData = (UserCacheData)jedisService.getObject(CacheKeyEnum.PREFIX_UESRCACHE,account);
        if(dataPermCache==null || userCacheData==null){
//            throw new TokenExpiredException(String.format("token过期", account));
            return false;
        }else {
            ThreadPermDataContext.set(dataPermCache);
            ThreadUserContext.set(userCacheData);
            return true;
        }
    }
}
